package sunyu.realm;

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import sunyu.mapper.ShiroPermissionMapper;
import sunyu.mapper.ShiroRoleMapper;
import sunyu.mapper.ShiroUserMapper;
import sunyu.pojo.shiro.ShiroInfo;
import sunyu.pojo.ShiroPermission;
import sunyu.pojo.ShiroRole;
import sunyu.pojo.ShiroUser;
import sunyu.toolkit.core.LogKit;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author 孙宇
 */
public class MyRealm extends AuthorizingRealm {

    private static final Logger logger = LogKit.getLogger();

    @Resource(name = "shiroUserMapper")
    ShiroUserMapper shiroUserMapper;

    @Resource(name = "shiroRoleMapper")
    ShiroRoleMapper shiroRoleMapper;

    @Resource(name = "shiroPermissionMapper")
    ShiroPermissionMapper shiroPermissionMapper;

    /**
     * 每次调用权限验证方法的时候，会触发这个方法
     * <p>
     * 例如调用subject.isPermitted("")时
     *
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        ShiroInfo shiroInfo = (ShiroInfo) this.getAuthenticationCacheKey(principals);
        info.setRoles(shiroInfo.getRoles());
        info.setStringPermissions(shiroInfo.getPermissions());
        return info;
    }

    /**
     * 调用subject.login(token);的时候，会触发这个方法
     *
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken authenticationToken = (UsernamePasswordToken) token;
        String loginName = authenticationToken.getUsername();//登录名称

        Map userParams = new HashMap() {{
            put("loginName", loginName);
        }};

        List<ShiroUser> ul = shiroUserMapper.select(userParams);

        if (ul != null && ul.size() > 0) {
            Set<String> roles = new HashSet<>();//数据库查出来的用户的角色集合
            Set<String> permissions = new HashSet<>();//数据库查出来的用户的许可集合

            Map params = new HashMap() {{
                put("user", userParams);
            }};

            List<ShiroRole> rl = shiroRoleMapper.select(params);
            if (rl != null && rl.size() > 0) {
                for (ShiroRole r : rl) {
                    roles.add(r.getCode());
                }
            }

            List<ShiroPermission> pl = shiroPermissionMapper.select(params);
            if (pl != null && pl.size() > 0) {
                for (ShiroPermission p : pl) {
                    permissions.add(p.getCode());
                }
            }

            ShiroInfo shiroInfo = new ShiroInfo();
            shiroInfo.setRoles(roles);
            shiroInfo.setPermissions(permissions);

            return new SimpleAuthenticationInfo(shiroInfo, ul.get(0).getLogin_pwd(), getName());
        } else {
            throw new UnknownAccountException();
        }
    }
}
